package com.example.batch.monitor.core;

import io.micrometer.core.instrument.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 详细指标收集器
 * 继承自基础指标收集器,实现HealthIndicator接口
 * 提供SQL执行、连接池、事务等详细监控指标收集和健康检查功能
 */
@Slf4j
public class DetailedMetricsCollector extends MetricsCollector implements HealthIndicator {

    /** SQL执行时间统计,key=数据源名:SQL类型 */
    private final Map<String, Timer> sqlTimers = new ConcurrentHashMap<>();
    
    /** 慢查询统计,key=数据源名:SQL类型 */
    private final Map<String, Counter> slowQueryCounters = new ConcurrentHashMap<>();
    
    /** 结果集大小统计,key=数据源名 */
    private final Map<String, DistributionSummary> resultSetSummaries = new ConcurrentHashMap<>();
    
    /** 事务统计,key=数据源名 */
    private final Map<String, Timer> transactionTimers = new ConcurrentHashMap<>();
    
    /** 慢查询阈值(ms) */
    private final long slowQueryThreshold;
    
    /** 大结果集阈值(行) */
    private final int largeResultSetThreshold;
    
    /** 健康检查阈值 */
    private final double healthCheckThreshold;

    /**
     * 构造函数
     * @param registry 指标注册表
     * @param applicationName 应用名称,用于标记指标来源
     * @param properties 监控配置属性
     */
    public DetailedMetricsCollector(
            MeterRegistry registry,
            String applicationName, 
            MonitorProperties properties) {
        super(registry, applicationName);
        this.slowQueryThreshold = properties.getSlowQueryThreshold();
        this.largeResultSetThreshold = properties.getLargeResultSetThreshold();
        this.healthCheckThreshold = properties.getHealthCheckThreshold();
    }

    /**
     * 记录SQL执行指标
     * @param dataSource 数据源名称
     * @param sqlType SQL类型(SELECT/INSERT等)
     * @param executionTime 执行时间(ms)
     * @param resultSetSize 结果集大小
     * @param tags 额外标签
     */
    public void recordSqlExecution(
            String dataSource,
            String sqlType, 
            long executionTime,
            int resultSetSize,
            Map<String, String> tags) {
            
        // 记录执行时间
        Timer timer = getOrCreateSqlTimer(dataSource, sqlType, tags);
        timer.record(executionTime, TimeUnit.MILLISECONDS);
        
        // 记录结果集大小
        if (resultSetSize > 0) {
            DistributionSummary summary = getOrCreateResultSetSummary(dataSource);
            summary.record(resultSetSize);
            
            // 大结果集告警
            if (resultSetSize > largeResultSetThreshold) {
                log.warn("Large result set detected - dataSource:{}, size:{}", 
                    dataSource, resultSetSize);
            }
        }
        
        // 慢查询统计
        if (executionTime > slowQueryThreshold) {
            Counter counter = getOrCreateSlowQueryCounter(dataSource, sqlType);
            counter.increment();
            
            // 慢查询告警
            log.warn("Slow query detected - dataSource:{}, type:{}, time:{}ms",
                dataSource, sqlType, executionTime);
        }
    }

    /**
     * 记录事务执行指标
     * @param dataSource 数据源名称
     * @param status 事务状态(COMMITTED/ROLLED_BACK)
     * @param executionTime 事务执行时间(ms)
     * @param operationCount 事务中的操作数量
     */
    public void recordTransactionExecution(
            String dataSource,
            String status,
            long executionTime,
            int operationCount) {
            
        // 记录事务执行时间
        Timer timer = getOrCreateTransactionTimer(dataSource);
        timer.record(executionTime, TimeUnit.MILLISECONDS);
        
        // 记录事务状态
        Counter.builder("transaction.status")
            .tag("dataSource", dataSource)
            .tag("status", status)
            .register(registry)
            .increment();
            
        // 记录事务操作数
        Gauge.builder("transaction.operations", operationCount)
            .tag("dataSource", dataSource)
            .register(registry);
            
        // 事务执行时间过长告警
        if (executionTime > slowQueryThreshold) {
            log.warn("Long transaction detected - dataSource:{}, time:{}ms, operations:{}",
                dataSource, executionTime, operationCount);
        }
    }

    /**
     * 获取或创建SQL执行计时器
     * @param dataSource 数据源名称
     * @param sqlType SQL类型
     * @param tags 额外标签
     * @return Timer SQL执行计时器
     */
    private Timer getOrCreateSqlTimer(String dataSource, String sqlType, Map<String, String> tags) {
        String key = String.format("%s:%s", dataSource, sqlType);
        return sqlTimers.computeIfAbsent(key, k -> {
            Timer.Builder builder = Timer.builder("sql.execution")
                .tag("dataSource", dataSource)
                .tag("type", sqlType)
                .publishPercentiles(0.5, 0.95, 0.99) // 发布50/95/99分位数
                .publishPercentileHistogram();  // 发布直方图数据
                
            // 添加自定义标签
            tags.forEach(builder::tag);
            
            return builder.register(registry);
        });
    }

    /**
     * 获取或创建结果集大小统计器
     * @param dataSource 数据源名称
     * @return DistributionSummary 结果集大小统计器
     */
    private DistributionSummary getOrCreateResultSetSummary(String dataSource) {
        return resultSetSummaries.computeIfAbsent(dataSource, k ->
            DistributionSummary.builder("sql.resultset.size")
                .tag("dataSource", dataSource)
                .publishPercentiles(0.5, 0.95, 0.99)
                .baseUnit("rows")
                .register(registry));
    }

    /**
     * 获取或创建慢查询计数器
     * @param dataSource 数据源名称
     * @param sqlType SQL类型
     * @return Counter 慢查询计数器
     */
    private Counter getOrCreateSlowQueryCounter(String dataSource, String sqlType) {
        String key = String.format("%s:%s", dataSource, sqlType);
        return slowQueryCounters.computeIfAbsent(key, k ->
            Counter.builder("sql.slow.query")
                .tag("dataSource", dataSource)
                .tag("type", sqlType)
                .register(registry));
    }

    /**
     * 获取或创建事务计时器
     * @param dataSource 数据源名称
     * @return Timer 事务计时器
     */
    private Timer getOrCreateTransactionTimer(String dataSource) {
        return transactionTimers.computeIfAbsent(dataSource, k ->
            Timer.builder("transaction.execution")
                .tag("dataSource", dataSource)
                .publishPercentiles(0.5, 0.95, 0.99)
                .publishPercentileHistogram()
                .register(registry));
    }

    /**
     * 实现健康检查接口
     * 基于慢查询比例、错误率等指标进行健康状态评估
     * @return Health 健康状态
     */
    @Override
    public Health health() {
        try {
            // 收集所有数据源的健康状态
            Map<String, Object> details = new HashMap<>();
            boolean isHealthy = true;
            
            // 遍历所有数据源
            Set<String> dataSources = getDataSources();
            for (String dataSource : dataSources) {
                // 计算关键指标
                double slowQueryRatio = getSlowQueryRatio(dataSource);
                double errorRate = getErrorRate(dataSource);
                double avgResponseTime = getAverageResponseTime(dataSource);
                
                // 评估健康状态
                boolean dsHealthy = slowQueryRatio < healthCheckThreshold
                    && errorRate < healthCheckThreshold
                    && avgResponseTime < slowQueryThreshold;
                    
                // 记录详细信息
                details.put(dataSource + ".slowQueryRatio", slowQueryRatio);
                details.put(dataSource + ".errorRate", errorRate);
                details.put(dataSource + ".avgResponseTime", avgResponseTime);
                details.put(dataSource + ".status", dsHealthy ? "UP" : "DOWN");
                
                isHealthy &= dsHealthy;
            }
            
            // 构建健康状态响应
            return isHealthy
                ? Health.up().withDetails(details).build()
                : Health.down().withDetails(details).build();
                
        } catch (Exception e) {
            log.error("Health check failed", e);
            return Health.down(e).build();
        }
    }

    /**
     * 获取数据源的慢查询比例
     * @param dataSource 数据源名称
     * @return double 慢查询比例
     */
    private double getSlowQueryRatio(String dataSource) {
        double totalQueries = getTotalQueries(dataSource);
        if (totalQueries == 0) {
            return 0.0;
        }
        return getSlowQueries(dataSource) / totalQueries;
    }

    /**
     * 获取数据源的错误率
     * @param dataSource 数据源名称
     * @return double 错误率
     */
    private double getErrorRate(String dataSource) {
        double totalExecutions = getTotalQueries(dataSource);
        if (totalExecutions == 0) {
            return 0.0;
        }
        return getErrorCount(dataSource) / totalExecutions;
    }

    /**
     * 获取数据源的平均响应时间
     * @param dataSource 数据源名称
     * @return double 平均响应时间(ms)
     */
    private double getAverageResponseTime(String dataSource) {
        return sqlTimers.entrySet().stream()
            .filter(e -> e.getKey().startsWith(dataSource + ":"))
            .mapToDouble(e -> e.getValue().mean(TimeUnit.MILLISECONDS))
            .average()
            .orElse(0.0);
    }

    // ... 其他辅助方法
} 